#pragma once

/*************************	Header *****************************/

#include "hamiltonian.h"

using arma::field;
using arma::cx_mat;
using arma::uvec;

/*********************** Declaration ***************************/

// The Energy Bands Functor.
//
//	This function object is used to calculate the energy bands of
//	a Unit. This entails eigenvalue calculataion of the hamilton. 
//	This functor includes to date the calculation of the following:
//
//	-	The energy bands for a given Unit (a collection of 
//		connected atoms, see the class Unit)
//
// Options:
//	The options are public variables (accessable from outside the
//	class) and are set to default value at class construction time.
//
// (System*) system;		Default:	&System::Std
//		A pointer to the used system. The system contains variables 
//		needed to construct elements (coupling strengths etc.).
//		The system defaults to a statically generated system (the
//		standard system).
//
// (double) bias;			Default:	0
//		A double containing the current bias (for bi-layered 
//		systems).
//		The bias defaults to 0 i.e no bias.
//
// (k_val_type) k_val;			Default:	brillouinpath
//		A enum type containing the current k-path to use. It can be
//		either brillouinpath or userdefined.
//		The k_val defaults to a brillouinpath.
//
// (mat) k;			Default:	mat()
//		A double matrix containing the current k-points.
//		The k defaults to mat() i.e empty.
//
// (eig_val_type) eig_val;			Default:	all
//		A enum type containing the what eigen values to generate.
//		This can be all, count (a spec. number of eig), or interval
//		(a spec. value interval)
//		The eig_val defaults to all i.e all eigenvalues.
//
// (size_t) N_eig;			Default:	20
//		A size_t containing the amount of eigvalues to calculate. If
//		this count is to big it will get truncated at calc. time.
//		The N_eig defaults to 20.
//
// (double) eig_min, eig_max;			Default:	-1,1
//		Two doubles containing the interval of eigvalues to calculate.
//		The eig_min, eig_max defaults to -1,1.
//
// Usage:
//	This function includes the following public operating functions.
//
//	(EnergyBands &) operator()(int id)
//		This operator (use by simply appending () to a EnergyBands type 
//		variable) calculates the energy bands. The operator 
//		returns	the object it self for easy access to result.
//		The result is stored in the H result variable. The variable
//		may be retrieved immidiately after calculation i.e:
//		enBands.(id).bands // Calculate and retreive result.
// 
// Example:
//	Set options and get DoS:
//
//		EnergyBands enBands; // Generate a hamilton object
//
//		enBands.bias = current_bias; // Set the current bias
//
//		return enBands.(id).bands; // Calculate and return result.
class GRAPHENETOOLS_DLL_API EnergyBands
{
	
// Options:
public:
	// A pointer to the used system. The system contains variables 
	// needed to construct elements (coupling strengths etc.).
	System* system;
	// A double containing the current bias (for bi-layered 
	// systems).
	double bias;
	// A enum type containing the current k-path to use. It can be
	// either brillouinpath or userdefined.
	enum k_val_type { brillouinpath, userdefined } k_val;
	// A double matrix containing the current k-points.
	mat k;
	// A enum type containing the what eigen values to generate.
	// This can be all, count (a spec. number of eig), or interval
	// (a spec. value interval)
	enum eig_val_type { all, count, interval } eig_val;
	// A size_t containing the amount of eigvalues to calculate. If
	// this count is to big it will get truncated at calc. time.
	size_t N_eig;
	// Two doubles containing the interval of eigvalues to calculate.
	double eig_min, eig_max;

// Usage:
	
	// This operator (use by simply appending () to a EnergyBands type 
	// variable) calculates the energy bands. The operator 
	// returns	the object it self for easy access to result.
	EnergyBands & operator()(int id);
	
// Results:

	// The bands of a Unit. Use operator()(int id) to set.
	field<std::pair<vec2,double>> bands;

	EnergyBands(void);

protected:
	mat getBrillouin(int id) const;
	static mat interpolatePath(const mat &path, const long &points);
};

